{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "view-in-github"
   },
   "source": [
    "<a href=\"https://colab.research.google.com/github/SummerLife/EmbeddedSystem/blob/master/MachineLearning/project/07_minist/mnist_convnet.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "891s6sPctH_y"
   },
   "source": [
    "# Simple MNIST convnet\n",
    "\n",
    "**Description:** A simple convnet that achieves ~99% test accuracy on MNIST."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "u5l_1tJ3tH_z"
   },
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 35
    },
    "colab_type": "code",
    "id": "s9ruvEWftH_0",
    "outputId": "812830e2-f106-47b6-ea75-51afa0c872fc"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "UsageError: Line magic function `%tensorflow_version` not found.\n"
     ]
    }
   ],
   "source": [
    "# %tensorflow_version 1.x\n",
    "import numpy as np\n",
    "from tensorflow import keras\n",
    "from tensorflow.keras import layers\n",
    "\n",
    "import tensorflow\n",
    "print(tensorflow.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "fDy_BEy2tH_3"
   },
   "source": [
    "## Prepare the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 107
    },
    "colab_type": "code",
    "id": "ORAbF52ztH_4",
    "outputId": "6c8ce3e3-6ea6-4c2d-c6a1-8942fd2aa433"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz\n",
      "11493376/11490434 [==============================] - 0s 0us/step\n",
      "x_train shape: (60000, 28, 28, 1)\n",
      "60000 train samples\n",
      "10000 test samples\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# Model / data parameters\n",
    "num_classes = 10\n",
    "input_shape = (28, 28, 1)\n",
    "\n",
    "# the data, split between train and test sets\n",
    "(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()\n",
    "\n",
    "# Scale images to the [0, 1] range\n",
    "x_train = x_train.astype(\"float32\") / 255\n",
    "x_test = x_test.astype(\"float32\") / 255\n",
    "# Make sure images have shape (28, 28, 1)\n",
    "x_train = np.expand_dims(x_train, -1)\n",
    "x_test = np.expand_dims(x_test, -1)\n",
    "print(\"x_train shape:\", x_train.shape)\n",
    "print(x_train.shape[0], \"train samples\")\n",
    "print(x_test.shape[0], \"test samples\")\n",
    "\n",
    "\n",
    "# convert class vectors to binary class matrices\n",
    "y_train = keras.utils.to_categorical(y_train, num_classes)\n",
    "y_test = keras.utils.to_categorical(y_test, num_classes)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "d0EDkUNFtH_6"
   },
   "source": [
    "## Build the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 487
    },
    "colab_type": "code",
    "id": "-AzUORibtH_7",
    "outputId": "fa03d84b-8e43-4f4f-fe72-8faca335289f"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /tensorflow-1.15.2/python3.6/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "If using Keras pass *_constraint arguments to layers.\n",
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d (Conv2D)              (None, 26, 26, 32)        320       \n",
      "_________________________________________________________________\n",
      "max_pooling2d (MaxPooling2D) (None, 13, 13, 32)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_1 (Conv2D)            (None, 11, 11, 64)        18496     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64)          0         \n",
      "_________________________________________________________________\n",
      "flatten (Flatten)            (None, 1600)              0         \n",
      "_________________________________________________________________\n",
      "dropout (Dropout)            (None, 1600)              0         \n",
      "_________________________________________________________________\n",
      "dense (Dense)                (None, 10)                16010     \n",
      "=================================================================\n",
      "Total params: 34,826\n",
      "Trainable params: 34,826\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "\n",
    "model = keras.Sequential(\n",
    "    [\n",
    "        keras.Input(shape=input_shape),\n",
    "        layers.Conv2D(32, kernel_size=(3, 3), activation=\"relu\"),\n",
    "        layers.MaxPooling2D(pool_size=(2, 2)),\n",
    "        layers.Conv2D(64, kernel_size=(3, 3), activation=\"relu\"),\n",
    "        layers.MaxPooling2D(pool_size=(2, 2)),\n",
    "        layers.Flatten(),\n",
    "        layers.Dropout(0.5),\n",
    "        layers.Dense(num_classes, activation=\"softmax\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "model.summary()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "GWw7ylFTtH_9"
   },
   "source": [
    "## Train the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 593
    },
    "colab_type": "code",
    "id": "gdO8tl4otH_-",
    "outputId": "65ad6759-0423-4208-dde5-a529fa63db2e"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 54000 samples, validate on 6000 samples\n",
      "Epoch 1/15\n",
      "54000/54000 [==============================] - 8s 145us/sample - loss: 0.3611 - acc: 0.8917 - val_loss: 0.0804 - val_acc: 0.9780\n",
      "Epoch 2/15\n",
      "54000/54000 [==============================] - 2s 30us/sample - loss: 0.1141 - acc: 0.9653 - val_loss: 0.0578 - val_acc: 0.9845\n",
      "Epoch 3/15\n",
      "54000/54000 [==============================] - 2s 30us/sample - loss: 0.0851 - acc: 0.9735 - val_loss: 0.0508 - val_acc: 0.9863\n",
      "Epoch 4/15\n",
      "54000/54000 [==============================] - 2s 30us/sample - loss: 0.0711 - acc: 0.9779 - val_loss: 0.0421 - val_acc: 0.9892\n",
      "Epoch 5/15\n",
      "54000/54000 [==============================] - 2s 30us/sample - loss: 0.0624 - acc: 0.9807 - val_loss: 0.0382 - val_acc: 0.9900\n",
      "Epoch 6/15\n",
      "54000/54000 [==============================] - 2s 30us/sample - loss: 0.0558 - acc: 0.9826 - val_loss: 0.0382 - val_acc: 0.9908\n",
      "Epoch 7/15\n",
      "54000/54000 [==============================] - 2s 30us/sample - loss: 0.0518 - acc: 0.9843 - val_loss: 0.0335 - val_acc: 0.9913\n",
      "Epoch 8/15\n",
      "54000/54000 [==============================] - 2s 30us/sample - loss: 0.0489 - acc: 0.9846 - val_loss: 0.0340 - val_acc: 0.9918\n",
      "Epoch 9/15\n",
      "54000/54000 [==============================] - 2s 30us/sample - loss: 0.0448 - acc: 0.9860 - val_loss: 0.0330 - val_acc: 0.9905\n",
      "Epoch 10/15\n",
      "54000/54000 [==============================] - 2s 31us/sample - loss: 0.0414 - acc: 0.9867 - val_loss: 0.0301 - val_acc: 0.9910\n",
      "Epoch 11/15\n",
      "54000/54000 [==============================] - 2s 32us/sample - loss: 0.0400 - acc: 0.9878 - val_loss: 0.0288 - val_acc: 0.9930\n",
      "Epoch 12/15\n",
      "54000/54000 [==============================] - 2s 32us/sample - loss: 0.0387 - acc: 0.9875 - val_loss: 0.0285 - val_acc: 0.9930\n",
      "Epoch 13/15\n",
      "54000/54000 [==============================] - 2s 32us/sample - loss: 0.0360 - acc: 0.9885 - val_loss: 0.0290 - val_acc: 0.9925\n",
      "Epoch 14/15\n",
      "54000/54000 [==============================] - 2s 32us/sample - loss: 0.0360 - acc: 0.9887 - val_loss: 0.0283 - val_acc: 0.9923\n",
      "Epoch 15/15\n",
      "54000/54000 [==============================] - 2s 32us/sample - loss: 0.0322 - acc: 0.9894 - val_loss: 0.0272 - val_acc: 0.9917\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<tensorflow.python.keras.callbacks.History at 0x7f78ff40c9b0>"
      ]
     },
     "execution_count": 8,
     "metadata": {
      "tags": []
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "batch_size = 128\n",
    "epochs = 15\n",
    "\n",
    "model.compile(loss=\"categorical_crossentropy\", optimizer=\"adam\", metrics=[\"accuracy\"])\n",
    "\n",
    "model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "H6LFmZ11tIAA"
   },
   "source": [
    "## Evaluate the trained model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 53
    },
    "colab_type": "code",
    "id": "JLtypPbwtIAB",
    "outputId": "01c8c067-c00c-4ec9-8f31-8dad93ce1013"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test loss: 0.024214195071693395\n",
      "Test accuracy: 0.9913\n"
     ]
    }
   ],
   "source": [
    "\n",
    "score = model.evaluate(x_test, y_test, verbose=0)\n",
    "print(\"Test loss:\", score[0])\n",
    "print(\"Test accuracy:\", score[1])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Soa4vXnmtti3"
   },
   "source": [
    "## Save the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "JKikkQu1trw6"
   },
   "outputs": [],
   "source": [
    "model.save(\"minist.h5\")"
   ]
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "collapsed_sections": [],
   "include_colab_link": true,
   "name": "mnist_convnet.ipynb",
   "provenance": [],
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
